package ga.cross;

import ga.GARun;
import ga.individuals.Individual;

import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

public class Multiple implements CrossMethod {
	private int firstCrossPoint, sndCrossPoint;
	
	public Multiple() {
		Random crossPointGen = new Random(System.currentTimeMillis());
		this.firstCrossPoint = crossPointGen.nextInt(GARun.bitsInDouble);
		
		do {
			this.sndCrossPoint = crossPointGen.nextInt(GARun.bitsInDouble);
		}while(this.sndCrossPoint == this.firstCrossPoint);
		
	}
	
	@Override
	public Collection<Individual> method(Collection<Individual> individuals) {
		int higherCrossPoint = this.firstCrossPoint > this.sndCrossPoint ? this.firstCrossPoint : this.sndCrossPoint;
		long mask1, mask2, maskaux, firstOffSpring, sndOffspring;
		List<Individual> offsprings = new LinkedList<Individual>();
		
		/* El cruce se hace entre dos individuos */
		if (individuals.size() != 2) {
			return null;
		}

		mask1 = maskaux = 0xFFFFFFFFFFFFFFFFL;
		
		List<Individual> listIndividuals = new LinkedList<Individual>(individuals);
		Long firstIndividual = Double.doubleToRawLongBits(listIndividuals.get(0).getIndividualValue());
		Long sndIndividual = Double.doubleToRawLongBits(listIndividuals.get(1).getIndividualValue());
		
		mask1 <<= higherCrossPoint;
		maskaux >>>= higherCrossPoint;
		mask1 |= maskaux;
		mask2 = ~mask1;
		
		firstOffSpring = (firstIndividual & mask1) | (sndIndividual & mask2);
		sndOffspring = (sndIndividual  & mask1) | (firstIndividual & mask2);;
		
		offsprings.add(new Individual(Double.longBitsToDouble(firstOffSpring)));
		offsprings.add(new Individual(Double.longBitsToDouble(sndOffspring)));
		return offsprings;
	}

}
